{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "colab": {
      "name": "linearregression.ipynb",
      "provenance": [],
      "collapsed_sections": []
    },
    "kernelspec": {
      "name": "python3",
      "display_name": "Python 3"
    }
  },
  "cells": [
    {
      "cell_type": "code",
      "metadata": {
        "id": "x1lvvYoqh_B8",
        "outputId": "8c73fe22-6d7f-4e12-ac70-acb4284f613e",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "from __future__ import absolute_import, division, print_function, unicode_literals\n",
        "import pathlib\n",
        "import matplotlib.pyplot as plt\n",
        "import numpy as np\n",
        "import pandas as pd\n",
        "import seaborn as sns\n",
        "from datetime import datetime\n",
        "import tensorflow as tf\n",
        "from tensorflow import keras\n",
        "from tensorflow.keras import layers\n",
        "print(tf.__version__)"
      ],
      "execution_count": 1,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "2.3.0\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "q5aSajJaiIaM"
      },
      "source": [
        "# Download the daset with keras.utils.get_file\n",
        "dataset_path = keras.utils.get_file(\"housing.data\", \"https://archive.ics.uci.edu/ml/machine-learning-databases/housing/housing.data\")"
      ],
      "execution_count": 2,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "e0DLwCqBASbu",
        "outputId": "7ab5c23e-cf36-466d-a850-cb2682584f84",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 363
        }
      },
      "source": [
        "column_names = ['CRIM','ZN','INDUS','CHAS','NOX',\n",
        "                'RM', 'AGE', 'DIS','RAD','TAX','PTRATION', 'B', 'LSTAT', 'MEDV']\n",
        "raw_dataset = pd.read_csv(dataset_path, names=column_names,\n",
        "                      na_values = \"?\", comment='\\t',\n",
        "                      sep=\" \", skipinitialspace=True)\n",
        "# Create a dataset instant\n",
        "dataset = raw_dataset.copy()\n",
        "\n",
        "# This function returns last n rows from the object \n",
        "# based on position.\n",
        "dataset.tail(n=10)"
      ],
      "execution_count": 3,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/html": [
              "<div>\n",
              "<style scoped>\n",
              "    .dataframe tbody tr th:only-of-type {\n",
              "        vertical-align: middle;\n",
              "    }\n",
              "\n",
              "    .dataframe tbody tr th {\n",
              "        vertical-align: top;\n",
              "    }\n",
              "\n",
              "    .dataframe thead th {\n",
              "        text-align: right;\n",
              "    }\n",
              "</style>\n",
              "<table border=\"1\" class=\"dataframe\">\n",
              "  <thead>\n",
              "    <tr style=\"text-align: right;\">\n",
              "      <th></th>\n",
              "      <th>CRIM</th>\n",
              "      <th>ZN</th>\n",
              "      <th>INDUS</th>\n",
              "      <th>CHAS</th>\n",
              "      <th>NOX</th>\n",
              "      <th>RM</th>\n",
              "      <th>AGE</th>\n",
              "      <th>DIS</th>\n",
              "      <th>RAD</th>\n",
              "      <th>TAX</th>\n",
              "      <th>PTRATION</th>\n",
              "      <th>B</th>\n",
              "      <th>LSTAT</th>\n",
              "      <th>MEDV</th>\n",
              "    </tr>\n",
              "  </thead>\n",
              "  <tbody>\n",
              "    <tr>\n",
              "      <th>496</th>\n",
              "      <td>0.28960</td>\n",
              "      <td>0.0</td>\n",
              "      <td>9.69</td>\n",
              "      <td>0</td>\n",
              "      <td>0.585</td>\n",
              "      <td>5.390</td>\n",
              "      <td>72.9</td>\n",
              "      <td>2.7986</td>\n",
              "      <td>6</td>\n",
              "      <td>391.0</td>\n",
              "      <td>19.2</td>\n",
              "      <td>396.90</td>\n",
              "      <td>21.14</td>\n",
              "      <td>19.7</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>497</th>\n",
              "      <td>0.26838</td>\n",
              "      <td>0.0</td>\n",
              "      <td>9.69</td>\n",
              "      <td>0</td>\n",
              "      <td>0.585</td>\n",
              "      <td>5.794</td>\n",
              "      <td>70.6</td>\n",
              "      <td>2.8927</td>\n",
              "      <td>6</td>\n",
              "      <td>391.0</td>\n",
              "      <td>19.2</td>\n",
              "      <td>396.90</td>\n",
              "      <td>14.10</td>\n",
              "      <td>18.3</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>498</th>\n",
              "      <td>0.23912</td>\n",
              "      <td>0.0</td>\n",
              "      <td>9.69</td>\n",
              "      <td>0</td>\n",
              "      <td>0.585</td>\n",
              "      <td>6.019</td>\n",
              "      <td>65.3</td>\n",
              "      <td>2.4091</td>\n",
              "      <td>6</td>\n",
              "      <td>391.0</td>\n",
              "      <td>19.2</td>\n",
              "      <td>396.90</td>\n",
              "      <td>12.92</td>\n",
              "      <td>21.2</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>499</th>\n",
              "      <td>0.17783</td>\n",
              "      <td>0.0</td>\n",
              "      <td>9.69</td>\n",
              "      <td>0</td>\n",
              "      <td>0.585</td>\n",
              "      <td>5.569</td>\n",
              "      <td>73.5</td>\n",
              "      <td>2.3999</td>\n",
              "      <td>6</td>\n",
              "      <td>391.0</td>\n",
              "      <td>19.2</td>\n",
              "      <td>395.77</td>\n",
              "      <td>15.10</td>\n",
              "      <td>17.5</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>500</th>\n",
              "      <td>0.22438</td>\n",
              "      <td>0.0</td>\n",
              "      <td>9.69</td>\n",
              "      <td>0</td>\n",
              "      <td>0.585</td>\n",
              "      <td>6.027</td>\n",
              "      <td>79.7</td>\n",
              "      <td>2.4982</td>\n",
              "      <td>6</td>\n",
              "      <td>391.0</td>\n",
              "      <td>19.2</td>\n",
              "      <td>396.90</td>\n",
              "      <td>14.33</td>\n",
              "      <td>16.8</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>501</th>\n",
              "      <td>0.06263</td>\n",
              "      <td>0.0</td>\n",
              "      <td>11.93</td>\n",
              "      <td>0</td>\n",
              "      <td>0.573</td>\n",
              "      <td>6.593</td>\n",
              "      <td>69.1</td>\n",
              "      <td>2.4786</td>\n",
              "      <td>1</td>\n",
              "      <td>273.0</td>\n",
              "      <td>21.0</td>\n",
              "      <td>391.99</td>\n",
              "      <td>9.67</td>\n",
              "      <td>22.4</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>502</th>\n",
              "      <td>0.04527</td>\n",
              "      <td>0.0</td>\n",
              "      <td>11.93</td>\n",
              "      <td>0</td>\n",
              "      <td>0.573</td>\n",
              "      <td>6.120</td>\n",
              "      <td>76.7</td>\n",
              "      <td>2.2875</td>\n",
              "      <td>1</td>\n",
              "      <td>273.0</td>\n",
              "      <td>21.0</td>\n",
              "      <td>396.90</td>\n",
              "      <td>9.08</td>\n",
              "      <td>20.6</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>503</th>\n",
              "      <td>0.06076</td>\n",
              "      <td>0.0</td>\n",
              "      <td>11.93</td>\n",
              "      <td>0</td>\n",
              "      <td>0.573</td>\n",
              "      <td>6.976</td>\n",
              "      <td>91.0</td>\n",
              "      <td>2.1675</td>\n",
              "      <td>1</td>\n",
              "      <td>273.0</td>\n",
              "      <td>21.0</td>\n",
              "      <td>396.90</td>\n",
              "      <td>5.64</td>\n",
              "      <td>23.9</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>504</th>\n",
              "      <td>0.10959</td>\n",
              "      <td>0.0</td>\n",
              "      <td>11.93</td>\n",
              "      <td>0</td>\n",
              "      <td>0.573</td>\n",
              "      <td>6.794</td>\n",
              "      <td>89.3</td>\n",
              "      <td>2.3889</td>\n",
              "      <td>1</td>\n",
              "      <td>273.0</td>\n",
              "      <td>21.0</td>\n",
              "      <td>393.45</td>\n",
              "      <td>6.48</td>\n",
              "      <td>22.0</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>505</th>\n",
              "      <td>0.04741</td>\n",
              "      <td>0.0</td>\n",
              "      <td>11.93</td>\n",
              "      <td>0</td>\n",
              "      <td>0.573</td>\n",
              "      <td>6.030</td>\n",
              "      <td>80.8</td>\n",
              "      <td>2.5050</td>\n",
              "      <td>1</td>\n",
              "      <td>273.0</td>\n",
              "      <td>21.0</td>\n",
              "      <td>396.90</td>\n",
              "      <td>7.88</td>\n",
              "      <td>11.9</td>\n",
              "    </tr>\n",
              "  </tbody>\n",
              "</table>\n",
              "</div>"
            ],
            "text/plain": [
              "        CRIM   ZN  INDUS  CHAS    NOX  ...    TAX  PTRATION       B  LSTAT  MEDV\n",
              "496  0.28960  0.0   9.69     0  0.585  ...  391.0      19.2  396.90  21.14  19.7\n",
              "497  0.26838  0.0   9.69     0  0.585  ...  391.0      19.2  396.90  14.10  18.3\n",
              "498  0.23912  0.0   9.69     0  0.585  ...  391.0      19.2  396.90  12.92  21.2\n",
              "499  0.17783  0.0   9.69     0  0.585  ...  391.0      19.2  395.77  15.10  17.5\n",
              "500  0.22438  0.0   9.69     0  0.585  ...  391.0      19.2  396.90  14.33  16.8\n",
              "501  0.06263  0.0  11.93     0  0.573  ...  273.0      21.0  391.99   9.67  22.4\n",
              "502  0.04527  0.0  11.93     0  0.573  ...  273.0      21.0  396.90   9.08  20.6\n",
              "503  0.06076  0.0  11.93     0  0.573  ...  273.0      21.0  396.90   5.64  23.9\n",
              "504  0.10959  0.0  11.93     0  0.573  ...  273.0      21.0  393.45   6.48  22.0\n",
              "505  0.04741  0.0  11.93     0  0.573  ...  273.0      21.0  396.90   7.88  11.9\n",
              "\n",
              "[10 rows x 14 columns]"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 3
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "oSZGioPsAVk0"
      },
      "source": [
        "# Split data into train/test\n",
        "# p = training data portion\n",
        "p=0.8\n",
        "trainDataset = dataset.sample(frac=p,random_state=0)\n",
        "testDataset = dataset.drop(trainDataset.index)"
      ],
      "execution_count": 4,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "583E8sDHAW5s",
        "outputId": "85e16fda-f36e-4131-ed2d-214894a2d9e1",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 279
        }
      },
      "source": [
        "# Visual representation of training data\n",
        "import matplotlib.pyplot as plt\n",
        "fig, ax = plt.subplots()\n",
        "# With .pop() command, the associated columns are extracted.\n",
        "x = trainDataset['RM']\n",
        "y = trainDataset['MEDV']\n",
        "ax.scatter(x, y, edgecolors=(0, 0, 0))\n",
        "ax.set_xlabel('RM')\n",
        "ax.set_ylabel('MEDV')\n",
        "plt.show()"
      ],
      "execution_count": 5,
      "outputs": [
        {
          "output_type": "display_data",
          "data": {
            "image/png": "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\n",
            "text/plain": [
              "<Figure size 432x288 with 1 Axes>"
            ]
          },
          "metadata": {
            "tags": [],
            "needs_background": "light"
          }
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "zaWXTRI8AYPe"
      },
      "source": [
        "# Pop command return item and drop it from frame.\n",
        "# After using trainDataset.pop('RM'), the 'RM' column \n",
        "# does not exist in the trainDataset frame anymore!\n",
        "trainInput = trainDataset['RM']\n",
        "trainTarget = trainDataset['MEDV']\n",
        "testInput = testDataset['RM']\n",
        "testTarget = testDataset['MEDV']"
      ],
      "execution_count": 6,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "3g7FwG2kAaBd",
        "outputId": "62c854c0-b1e8-4fdc-c171-b1369aba58df",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "# We don't specify anything for activation -> no activation is applied (ie. \"linear\" activation: a(x) = x)\n",
        "# Check: https://www.tensorflow.org/api_docs/python/tf/keras/layers/Dense\n",
        "\n",
        "def linear_model():\n",
        "  model = keras.Sequential([\n",
        "        layers.Dense(1, use_bias=True, input_shape=(1,), name='layer')\n",
        "      ])\n",
        "\n",
        "  # Using adam optimizer\n",
        "  optimizer = tf.keras.optimizers.Adam(\n",
        "      learning_rate=0.01, beta_1=0.9, beta_2=0.99, epsilon=1e-05, amsgrad=False,\n",
        "      name='Adam')\n",
        "    \n",
        "  # Check: https://www.tensorflow.org/api_docs/python/tf/keras/Model\n",
        "  # loss: String (name of objective function), objective function or tf.keras.losses.Loss instance. See tf.keras.losses.\n",
        "  # optimizer: String (name of optimizer) or optimizer instance. See tf.keras.optimizers.\n",
        "  # metrics: List of metrics to be evaluated by the model during training and testing\n",
        "  model.compile(loss='mse', optimizer=optimizer, metrics=['mae','mse'])\n",
        "\n",
        "  return model\n",
        "\n",
        "# Create model instant\n",
        "model = linear_model()\n",
        "\n",
        "# Print the model summary\n",
        "model.summary()"
      ],
      "execution_count": 7,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "Model: \"sequential\"\n",
            "_________________________________________________________________\n",
            "Layer (type)                 Output Shape              Param #   \n",
            "=================================================================\n",
            "layer (Dense)                (None, 1)                 2         \n",
            "=================================================================\n",
            "Total params: 2\n",
            "Trainable params: 2\n",
            "Non-trainable params: 0\n",
            "_________________________________________________________________\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "XxqPOb8lAbhr",
        "outputId": "438ece86-4396-4c1b-b169-3bdb0b7486a9",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "# params\n",
        "n_epochs = 4000\n",
        "batch_size = 256\n",
        "n_idle_epochs = 100\n",
        "n_epochs_log = 200\n",
        "n_samples_save = n_epochs_log * trainInput.shape[0]\n",
        "print('Checkpoint is saved for each {} samples'.format(n_samples_save))\n",
        "\n",
        "# A mechanism that stops training if the validation loss is not improving for more than n_idle_epochs.\n",
        "#See https://www.tensorflow.org/api_docs/python/tf/keras/callbacks/EarlyStopping for details.\n",
        "earlyStopping = tf.keras.callbacks.EarlyStopping(monitor='val_loss', patience=n_idle_epochs, min_delta=0.001)\n",
        "\n",
        "# Creating a custom callback to print the log after a certain number of epochs\n",
        "# Check: https://www.tensorflow.org/api_docs/python/tf/keras/callbacks\n",
        "predictions_list = []\n",
        "class NEPOCHLogger(tf.keras.callbacks.Callback):\n",
        "    def __init__(self,per_epoch=100):\n",
        "        '''\n",
        "        display: Number of batches to wait before outputting loss\n",
        "        '''\n",
        "        self.seen = 0\n",
        "        self.per_epoch = per_epoch\n",
        "    \n",
        "    def on_epoch_end(self, epoch, logs=None):\n",
        "      if epoch % self.per_epoch == 0:\n",
        "        print('Epoch {}, loss {:.2f}, val_loss {:.2f}, mae {:.2f}, val_mae {:.2f}, mse {:.2f}, val_mse {:.2f}'\\\n",
        "              .format(epoch, logs['loss'], logs['val_loss'],logs['mae'], logs['val_mae'],logs['mse'], logs['val_mse']))\n",
        "              \n",
        "# Call the object\n",
        "log_display = NEPOCHLogger(per_epoch=n_epochs_log)\n",
        "\n",
        "# Include the epoch in the file name (uses `str.format`)\n",
        "import os\n",
        "checkpoint_path = \"training/cp-{epoch:05d}.ckpt\"\n",
        "checkpoint_dir = os.path.dirname(checkpoint_path)\n",
        "\n",
        "# Create a callback that saves the model's weights every 5 epochs\n",
        "checkpointCallback = tf.keras.callbacks.ModelCheckpoint(\n",
        "    filepath=checkpoint_path, \n",
        "    verbose=1, \n",
        "    save_weights_only=True,\n",
        "    save_freq=n_samples_save)\n",
        "\n",
        "# Save the weights using the `checkpoint_path` format\n",
        "model.save_weights(checkpoint_path.format(epoch=0))\n",
        "\n",
        "# Define the Keras TensorBoard callback.\n",
        "logdir=\"logs/fit/\" + datetime.now().strftime(\"%Y%m%d-%H%M%S\")\n",
        "tensorboard_callback = keras.callbacks.TensorBoard(log_dir=logdir)\n",
        "\n",
        "history = model.fit(\n",
        "  trainInput, trainTarget, batch_size=batch_size,\n",
        "  epochs=n_epochs, validation_split = 0.1, verbose=0, callbacks=[earlyStopping,log_display,tensorboard_callback,checkpointCallback])"
      ],
      "execution_count": 8,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "Checkpoint is saved for each 81000 samples\n",
            "WARNING:tensorflow:From /usr/local/lib/python3.6/dist-packages/tensorflow/python/ops/summary_ops_v2.py:1277: stop (from tensorflow.python.eager.profiler) is deprecated and will be removed after 2020-07-01.\n",
            "Instructions for updating:\n",
            "use `tf.profiler.experimental.stop` instead.\n",
            "WARNING:tensorflow:Callbacks method `on_train_batch_end` is slow compared to the batch time (batch time: 0.0017s vs `on_train_batch_end` time: 0.0120s). Check your callbacks.\n",
            "Epoch 0, loss 248.69, val_loss 316.44, mae 13.60, val_mae 14.84, mse 248.69, val_mse 316.44\n",
            "Epoch 200, loss 54.26, val_loss 91.20, mae 5.27, val_mae 6.75, mse 54.26, val_mse 91.20\n",
            "Epoch 400, loss 53.16, val_loss 90.61, mae 5.19, val_mae 6.68, mse 53.16, val_mse 90.61\n",
            "Epoch 600, loss 51.47, val_loss 89.30, mae 5.10, val_mae 6.58, mse 51.47, val_mse 89.30\n",
            "Epoch 800, loss 49.86, val_loss 88.29, mae 4.99, val_mae 6.47, mse 49.86, val_mse 88.29\n",
            "Epoch 1000, loss 48.52, val_loss 87.20, mae 4.92, val_mae 6.38, mse 48.52, val_mse 87.20\n",
            "Epoch 1200, loss 47.36, val_loss 86.52, mae 4.83, val_mae 6.32, mse 47.36, val_mse 86.52\n",
            "Epoch 1400, loss 46.40, val_loss 85.98, mae 4.77, val_mae 6.26, mse 46.40, val_mse 85.98\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "QlB3GPfZAdcA",
        "outputId": "c15c3ee7-6f61-4502-e2c0-b3ee125e337b",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 305
        }
      },
      "source": [
        "# The fit model returns the history object for each Keras model\n",
        "# Let's explore what is inside history\n",
        "print('keys:', history.history.keys())\n",
        "\n",
        "# Returning the desired values for plotting and turn to numpy array\n",
        "mae = np.asarray(history.history['mae'])\n",
        "val_mae = np.asarray(history.history['val_mae'])\n",
        "\n",
        "# Creating the data frame\n",
        "num_values = (len(mae))\n",
        "values = np.zeros((num_values,2), dtype=float)\n",
        "values[:,0] = mae\n",
        "values[:,1] = val_mae\n",
        "\n",
        "# Using pandas to frame the data\n",
        "steps = pd.RangeIndex(start=0,stop=num_values)\n",
        "data = pd.DataFrame(values, steps, columns=[\"training-mae\", \"val-mae\"])\n",
        "\n",
        "# Plotting\n",
        "sns.set(style=\"whitegrid\")\n",
        "sns.lineplot(data=data, palette=\"tab10\", linewidth=2.5)"
      ],
      "execution_count": 9,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "keys: dict_keys(['loss', 'mae', 'mse', 'val_loss', 'val_mae', 'val_mse'])\n"
          ],
          "name": "stdout"
        },
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "<matplotlib.axes._subplots.AxesSubplot at 0x7f8e90fdee80>"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 9
        },
        {
          "output_type": "display_data",
          "data": {
            "image/png": "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CaulpaVF/ec//xm9/bvf/U696aab1FAopJ5++unqxo0bVVVV1QcffFC98cYbVVVVe102EiorK9XLL79cPe2009SdO3eO6lpvv/129be//a2qKIqqqqra0NCgqmrv74FEvD8URVEXLFig7ty5U1VVVd2+fbs6b948NRQKjYpaN27cqB4+fDj6P+/P8yeq7p5qPdrnTFV7f4/G+/17tL+rqnb/nI1UrUkV6I2NjWpZWZkaDAZVVVXVYDColpWVqU1NTQmuTPPmm2+ql156qbp161b17LPPjs5vampS582bp6qq2uuyePP5fOoFF1ygVlVVRd9oo7VWl8ullpWVqS6Xq8v83t4DiXp/KIqifv3rX1c3bdqkqqqqfvrpp+qZZ5456mrtHC6DrW2k6u4pJCMinzNV7f09OlLv3yNr7elzNlK1JtVFomtqaigsLMRgMABgMBgoKCigpqaGnJzeL84ab4qi8Mwzz1BeXk5NTQ3jxo2LLsvJyUFRFFpbW3tdlpWVFdca77//fpYtW8aECbGrjY/WWquqqsjKymLdunV88skn2O12rrnmGqxW61HfA6qqJuT9odPpuO+++7jqqquw2Wy43W4ee+yxXt+viao1YrC1Jbruzp+zyOsYbe/fnj5nI1Vr0rWhj1a33347NpuNSy65JNGl9GjLli1UVlZy8cUXJ7qUfgmFQlRVVTFr1ixefPFFfvGLX/DTn/4Uj8eT6NK6CQaDPProozz00EO8++67PPzww1x77bWjstZkJ5+z3iXVHnpxcTF1dXWEQiEMBgOhUIj6+nqKi4sTWteaNWs4cOAAjzzyCHq9nuLiYg4fPhxd3tzcjF6vJysrq9dl8bRx40b27NnDwoULAaitreXyyy9n+fLlo65W0P7XRqORJUuWADB37lyys7OxWq1HfQ+oqpqQ98f27dupr6+nrKwMgLKyMtLS0rBYLKOu1ojePku91ZbIuo/8nEVex2h6/x7tc3bnnXeOSK1JtYeem5vLzJkzef311wF4/fXXmTlzZkKbW+655x4qKyt58MEHMZvNAMyePRuv18umTZsAePbZZ1m8eHGfy+Lpyiuv5B//+AfvvPMO77zzDkVFRTz++ONcccUVo65W0L5ynnjiiXz44YeA1rOiqamJyZMnH/U9kKj3R1FREbW1tezduxeAPXv20NTUxKRJk0ZdrRG9Pf9gl8VTT58zGH2ftaN9zk466aQRqTXphs/ds2cPN954I+3t7TgcDtasWcMxxxyTkFp2797NkiVLmDx5MlarFYAJEybw4IMPsnnzZlatWoXP52P8+PHcfffd5OXlAfS6bKSUl5fzyCOPMH369FFba1VVFTfffDOtra0YjUauvfZaTj311F7fA4l6f7z66qv84Q9/iI7t/7Of/YzTTz99VNS6evVqNmzYQGNjI9nZ2WRlZfHGG28MurZ41t1Trffdd99RP2fQ+3s0nu/fo/1dO+v8ORuJWpMu0IUQQvQsqZpchBBCHJ0EuhBCpAgJdCGESBES6EIIkSIk0IUQIkVIoAshRIqQQBdCiBQhgS6EECni/wP1utnDaCTm8wAAAABJRU5ErkJggg==\n",
            "text/plain": [
              "<Figure size 432x288 with 1 Axes>"
            ]
          },
          "metadata": {
            "tags": []
          }
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "hk4T7d3fAirT",
        "outputId": "8137b4d9-4b36-4ba0-e493-e5c8e590f367",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 289
        }
      },
      "source": [
        "predictions = model.predict(testInput).flatten()\n",
        "a = plt.axes(aspect='equal')\n",
        "plt.scatter(predictions, testTarget, edgecolors=(0, 0, 0))\n",
        "plt.xlabel('True Values')\n",
        "plt.ylabel('Predictions')\n",
        "lims = [0, 50]\n",
        "plt.xlim(lims)\n",
        "plt.ylim(lims)\n",
        "_ = plt.plot(lims, lims)"
      ],
      "execution_count": 10,
      "outputs": [
        {
          "output_type": "display_data",
          "data": {
            "image/png": "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\n",
            "text/plain": [
              "<Figure size 432x288 with 1 Axes>"
            ]
          },
          "metadata": {
            "tags": []
          }
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "qZLB8wmLAkSZ",
        "outputId": "a4918786-463a-4235-df8d-c520eb27e186",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "# Get the saved checkpoint files\n",
        "checkpoints = []\n",
        "for f_name in os.listdir(checkpoint_dir):\n",
        "  if f_name.startswith('cp-'):\n",
        "    file_with_no_ext = os.path.splitext(f_name)[0]\n",
        "    checkpoints.append(file_with_no_ext)\n",
        "\n",
        "# Return unique list elements\n",
        "checkpoints = list(set(checkpoints))\n",
        "print('checkpoints:',checkpoints)\n",
        "\n",
        "# Load all model checkpoints and evaluate for each\n",
        "count = 0\n",
        "model_improvement_progress = False\n",
        "if model_improvement_progress:\n",
        "  for checkpoint in checkpoints:\n",
        "    count += 1\n",
        "\n",
        "    # Call model instant\n",
        "    model = linear_model()\n",
        "    \n",
        "    # Restore the weights\n",
        "    path = os.path.join('training',checkpoint)\n",
        "    model.load_weights(path)\n",
        "\n",
        "    # Access to layer weights\n",
        "    layer = model.get_layer('layer')\n",
        "    w1,w0 = layer.get_weights()\n",
        "    w1 = float(w1[0])\n",
        "    w0 = float(w0[0])\n",
        "    \n",
        "    # Draw the scatter plot of data\n",
        "    fig, ax = plt.subplots()\n",
        "    x = testInput\n",
        "    y = testTarget\n",
        "    ax.scatter(x, y, edgecolors=(0, 0, 0))\n",
        "    ax.set_xlabel('RM')\n",
        "    ax.set_ylabel('MEDV')\n",
        "    \n",
        "    # Plot the line\n",
        "    y_hat = w1*x + w0\n",
        "    plt.plot(x, y_hat, '-r')\n"
      ],
      "execution_count": 12,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "checkpoints: ['cp-00000.ckpt']\n"
          ],
          "name": "stdout"
        }
      ]
    }
  ]
}